package program_storage;

import java.io.*;
import java.util.*;
import virtual_machine.*;

public class Main_Storage {

	/**
	 * ClassFileName containing the absolute path to the File
	 */
	String classFile;
	
	/**
	 * String representation of the Bytecode File
	 */
	String myProgramm;
	
	/**
	 * The Lexer for the BytecodeFile
	 */
	Lexer myMachineLexer;
	
	/**
	 * The Parser for the BytecodeFile
	 */
	Parser myParser;
	
	/**
	 * Map providing the Code-List for each Method
	 */
	Map<Integer, List<Code>> methodCodeMap= new HashMap<Integer, List<Code>>();
	
	/**
	 * Map providing the number of arguments for each method
	 */
	Map<Integer, Integer> methodNumberToArg = new HashMap<Integer, Integer>();
	
	/**
	 * List containing the code of the main-method
	 */
	List<Code> mainCodeList = new ArrayList<Code>();
	
	/**
	 * The Constructor; lexes, parses the Bytecode and fill the Maps and Lists
	 * @param classFile, containing Filename and absolute path
	 * @throws ParserException
	 */
	public Main_Storage(String classFile) throws ParserException {
		this.classFile = classFile;
		this.myProgramm = this.readClassFileToString();
		//System.out.println(this.myProgramm);
		this.myMachineLexer = new Lexer(new StringReader(this.myProgramm));
		this.myParser = new Parser(this.methodNumberToArg, this.myMachineLexer, this.methodCodeMap, this.mainCodeList);
		this.myParser.parse();
		this.mainCodeList = this.myParser.getMainCodeList();
		this.methodCodeMap = this.myParser.getMethodMap();
		this.methodNumberToArg = this.myParser.getMethodArgNumber();
		//System.err.println(this.mainCodeList.size());
		//System.err.println(this.methodCodeMap.size());
	}
	
	/**
	 * Reads the content of the BytecodeFile and saves it
	 * @return String representation of the BytecodeFile
	 */
	private String readClassFileToString() {
		String ruckgabe = "";
		File filename = new File (/*"/home/sebastian/Desktop/SO-Framework/SO-VM/src/virtual_machine/"+*/this.classFile);
		boolean doesexist = filename.exists();
		if (doesexist) {
			boolean readable = filename.canRead();
			if (readable) {
				try {
					FileReader reader = new FileReader(filename);
					BufferedReader input = new BufferedReader(reader);
					while (input.ready()) {
						ruckgabe = ruckgabe + input.readLine() + "\n";
					}
					input.close();
					reader.close();
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
			else {
				System.err.println("Datei kann nicht gelesen werden");
			}
		}
		else {
			System.err.println("Datei existiert nicht!");
		}
		return ruckgabe;
	}
	
	/**
	 * Getter
	 * @return {@link #mainCodeList}
	 */
	public List<Code> getMainCodeList() {
		return this.mainCodeList;
	}
	
	/**
	 * Getter
	 * @return {@link #methodCodeMap}
	 */
	public Map<Integer, List<Code>> getMethodCodeMap() {
		return this.methodCodeMap;
	}
	
	/**
	 * Getter
	 * @return {@link #methodNumberToArg}
	 */
	public Map<Integer, Integer> getMethodArgNumber() {
		return this.methodNumberToArg;
	}

}
